/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.karolinska.corticostriatal.ROI_plot;

import ij.IJ;
import ij.ImagePlus;
import ij.gui.ImageWindow;
import ij.gui.Plot;
import ij.gui.PlotWindow;
import ij.gui.Roi;
import ij.measure.Measurements;
import ij.process.ImageProcessor;
import ij.process.ImageStatistics;
import java.awt.Color;
import java.awt.Point;
import java.util.Random;
import org.micromanager.utils.ReportingUtils;

/**
 *
 * @author Matthijs
 */
public class plotHandler {
    
    
    private static  plotHandler             instance;
    private         Plot                    plot; 
    private         PlotWindow              plotWindow;
    private         double[][]              means;
    private         Color[]                 colors;
    
    
    /**
     *  Plot the ROI intensity values. Create a new plot window
     *  if necessary.
     */
    public static void plot () {
        ReportingUtils.logMessage("Starting plot handler.");
        Point location = null;
        
        if (instance != null) {
            instance.plotWindow.dispose();
            location = instance.plotWindow.getLocation();
        }
        if (roiHandler.getCount() < 1) {
            ROI_plot.scripts.showError("You must select at least one ROI.");
            return;
        }
        ImageWindow current = ij.WindowManager.getCurrentWindow();
        
        instance = new plotHandler();
        instance.loadData();
        instance.setMinMax();
        instance.generateColors();
        instance.plotMeans();
        instance.plotWindow = instance.plot.show();
        if (location != null)
            instance.plotWindow.setLocation(location);
        
        if (current != null)
            current.toFront();
    }
    
    
    /**
     *  Load the intensity data required to produce a plot. This uses the ImageJ
     *  functionality to set a region of interest (provided by our roiHandler 
     *  class) and retrieve its statistics.
     */
    private void loadData () {
        ImagePlus imp           = IJ.getImage();
        ImageProcessor ip       = imp.getProcessor();
        ImageStatistics stats   = null;
        Roi         current;
        
        int         count       = roiHandler.getCount();
        int         frames      = imp.getNFrames();
        means                   = new double[count][frames];
        
        ReportingUtils.logMessage("Found " + count + " regions of interest.");
        for (int i = 0; i < count; i++) {
            current = roiHandler.getROI(i);

            for (int j = 0; j < frames; j++) {
                imp.setT(j + 1);
                
                ip.setRoi(current); 
                stats       = ImageStatistics.getStatistics(ip, Measurements.MEAN, imp.getCalibration()); 
                means[i][j] = (float) stats.mean;
            }
        }
    }
    
    
    /**
     *  Generate time and mean data-traces, set a random color, and plot them.
     */
    private void plotMeans () {
        int         last        = means[0].length;
        double[]    time        = new double[last];
        double      interval    = Double.parseDouble(ROI_plot.dialog.frameTimeInput.getText());

        for (int i = 0; i < last; i++)
            time[i] = (i + 1) * interval;
        
        for (int i = 0; i < means.length; i++) {
            double[] roi = means[i];

            plot.setColor(colors[i]);
            plot.addPoints(time, roi, Plot.LINE);
            plot.addLabel(10, 10, "Region " + i);
        }        
    }
    
    
    /**
     *  Generate a number of random new colors, so that each ROI has its own
     *  color assigned to it in both the intensity plot as well as the ROI 
     *  plot.
     */
    private void generateColors () {
        Random rand = new Random();
        int count   = means.length;
        colors      = new Color[count];
        
        for (int i = 0; i < count; i++) {
            float r     = rand.nextFloat();
            float g     = rand.nextFloat();
            float b     = rand.nextFloat();
            colors[i]   = new Color(r, g, b);        
        }
        roiHandler.showROIs(colors);
    }
    
    
    /**
     *  Set the minimum and maximum Y values of the plot, based on
     *  the minimum and maximum intensity values.
     * 
     *  @param means 
     */
    private void setMinMax () {
        double  min         = Double.MAX_VALUE,
                max         = Double.MIN_VALUE,
                interval    = Double.parseDouble(ROI_plot.dialog.frameTimeInput.getText());
        
        for (double[] roi : means) {
            for (double frame : roi) {
                if (frame > max)
                    max = frame;
                if (frame < min)
                    min = frame;
            }
        }
        plot.setLimits(0, (means[0].length + 2) * interval, 0.95 * min, 1.05 * max);
    }
    
    
    /**
     *  Plothandler constructor. Creates a new plot.
     */
    private plotHandler () {
        plot = new Plot("Intensity", "Frame Number / Time [ms]", "Mean Intensity [cts]");
        plot.setFrameSize(800,400);
        plot.setLineWidth(2);
    }
}
